﻿
// 文件管理器Dlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "文件管理器.h"
#include "文件管理器Dlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// C文件管理器Dlg 对话框



C文件管理器Dlg::C文件管理器Dlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MY_DIALOG, pParent)
	, m_strCurrent(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void C文件管理器Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TREE1, m_tree);

	DDX_Control(pDX, IDC_LIST1, m_list);
	DDX_Control(pDX, IDC_COMBO1, m_combox);
	DDX_CBString(pDX, IDC_COMBO1, m_strCurrent);
}

BEGIN_MESSAGE_MAP(C文件管理器Dlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_NOTIFY(NM_DBLCLK, IDC_TREE1, &C文件管理器Dlg::OnDblclkTree1)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &C文件管理器Dlg::OnDblclkList1)
	ON_BN_CLICKED(IDC_BUTTON4, &C文件管理器Dlg::OnBnClickedButton4)
	ON_WM_SIZE()
	ON_WM_GETMINMAXINFO()
END_MESSAGE_MAP()


// C文件管理器Dlg 消息处理程序

BOOL C文件管理器Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码


	//初始化树box 控件：
	HTREEITEM hRootitem =   m_tree.InsertItem(L"my computer");
#if 0
	//手动添加树内容
	HTREEITEM hItem =   m_tree.InsertItem(L"c:",hRootitem);


	m_tree.InsertItem(L"c:", hRootitem);
	m_tree.InsertItem(L"d:", hRootitem);
	m_tree.InsertItem(L"e:", hRootitem);

	m_tree.InsertItem(L"a:", hItem);
	m_tree.InsertItem(L"b:", hItem);
#else

	//自动获取：
	TCHAR buff[256] = { 0 };
	int len = GetLogicalDriveStrings(256, buff);		//如果函数成功，则返回值是复制到缓冲区的字符串的长度（以字符为单位）
	for (int i = 0; i < len / 4/*每一个都是四个字节*/; i++)
	{
		CString str = buff + i * 4;
		m_tree.InsertItem(str, hRootitem);
	}


#endif



	//初始化列表box 控件：
	m_list.ModifyStyle(0,
		LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_VSCROLL | WS_BORDER);
	m_list.InsertColumn(0, L"文件名", LVCFMT_LEFT, 350);
	m_list.InsertColumn(1, L"修改时间", LVCFMT_LEFT, 350);
	m_list.InsertColumn(2, L"文件类型", LVCFMT_LEFT, 350);
	m_list.InsertColumn(3, L"文件大小", LVCFMT_LEFT, 350);

	//设置列表风格为整行选取：
	m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void C文件管理器Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void C文件管理器Dlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR C文件管理器Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void C文件管理器Dlg::OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
	// TODO: 在此添加控件通知处理程序代码

	//找到对应盘符下面的所有文件		并显示：
	
	HTREEITEM hRootItem = 	m_tree.GetRootItem();		//拿到根
	HTREEITEM hSel =  m_tree.GetSelectedItem();			//拿到被选中的哪一个

	if (hRootItem == hSel)
	{
		return;		//如果拿到的是根盘符 就没事了；
	}

	//是否有孩子：
	if (m_tree.ItemHasChildren(hSel))	return;



	//记录当前路径：
	m_strCurrent = GetTreePath(hSel);


	//去掉我的电脑：
	CString strFindstr = L"my computer\\";
	int nPos = m_strCurrent.Find(strFindstr);
	if (0 == nPos)
	{
		m_strCurrent = m_strCurrent.Mid(strFindstr.GetLength());
	}

	m_strCurrent.Replace(L"\\\\", L"\\");

	//找文件：
	Find(m_strCurrent, hSel);


	UpdateData(false);

	*pResult = 0;
}


// 查找strPath目录下所有文件 并显示到list控件中
void C文件管理器Dlg::Find(CString strPath,HTREEITEM hTreeItem)
{
	// TODO: 在此处添加实现代码.

	//清理掉list控件中之前的：
	m_list.DeleteAllItems();

	//把右边多余的\去掉
	strPath.TrimRight('\\');

	//显示为 树控件当前item的孩子
	CFileFind find;
	CString strFind = strPath + L"*.*";

	bool isfind = find.FindFile(strFind);		//找一个文件
	int i = 0;

	while (isfind)
	{
		isfind = find.FindNextFile();

		//跳过隐藏的文件和系统文件：
		if (find.IsHidden() || find.IsSystem())
		{
			continue;		//跳过
		}

		//获取文件名：
		CString filename = find.GetFileName();

		if (filename == L".")
		{
			continue;
		}
		if (filename == L"..")
		{
			filename = L"返回上一级";

		}

		//获取文件信息  （图标，文件类型）：

		SHFILEINFO shfi = { 0 };

		HIMAGELIST imagelist = (HIMAGELIST) SHGetFileInfo(strPath + L"\\" + filename,
			FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL,
			&shfi,sizeof(shfi),
			SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_TYPENAME);

		m_list.SetImageList(CImageList::FromHandle(imagelist),
			LVSIL_SMALL);

		m_list.InsertItem(i, filename, shfi.iIcon);


		if (hTreeItem)
		{
			m_tree.InsertItem(filename, hTreeItem);
		}

		if (find.IsDirectory())		//如果是文件夹
		{
			if (find.IsDots())			//如果是点
			{
				m_list.SetItemData(i, 0);	//返回上一级
			}
			else
			{
				m_list.SetItemData(i, 1);	//普通文件夹

				m_list.SetItemText(i, 2, shfi.szTypeName);

				//修改时间：
				CTime filetime;
				find.GetLastWriteTime(filetime);
				m_list.SetItemText(i, 1,
					filetime.Format(L"%Y-%m-%d	 %H:%M:%S"));

			}
		}
		else                               //当前是文件
		{
			//文件大小：								如果是文件夹的大小都是0字节
			ULONGLONG uFindsize = find.GetLength();
			wchar_t szFilesize[56];
			StrFormatByteSize(uFindsize, szFilesize, 56);
			m_list.SetItemText(i, 3, szFilesize);
			m_list.SetItemText(i, 2, shfi.szTypeName);
			m_list.SetItemData(i, 2);		//2：文件		1：文件夹		0：返回上一级


			//修改时间：
			CTime filetime;
			find.GetLastWriteTime(filetime);
			m_list.SetItemText(i, 1,
				filetime.Format(L"%Y-%m-%d	 %H:%M:%S"));

		}

		
		//m_list.InsertItem(i, filename);


		
		i++;
	}
}


void C文件管理器Dlg::OnDblclkList1(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码

	//获取当前选中的那一个行：
	POSITION pos =  m_list.GetFirstSelectedItemPosition();

	int sel = m_list.GetNextSelectedItem(pos);

	//获取选中内容：
	DWORD data  = m_list.GetItemData(sel);



	//获取这一行的文件名：
	CString filename = m_list.GetItemText(sel, 0);


	//地址栏显示：
	m_strCurrent = m_strCurrent + L"\\" +  filename;


	//只显示一个' \'
	m_strCurrent.Replace(L"\\\\", L"\\");


	if (0 == data)
	{
		int nPos = m_strCurrent.ReverseFind(L'\\');
		m_strCurrent = m_strCurrent.Mid(0, nPos);


		nPos = m_strCurrent.ReverseFind(L'\\');
		m_strCurrent = m_strCurrent.Mid(0, nPos);
	}



	UpdateData(false);
	Find(m_strCurrent,NULL);



	*pResult = 0;
}


// 去获取父控件的item
CString C文件管理器Dlg::GetTreePath(HTREEITEM hTreeItem)
{
	// TODO: 在此处添加实现代码.

	CString strItemText = m_tree.GetItemText(hTreeItem);




	HTREEITEM hParentItem = m_tree.GetParentItem(hTreeItem);

	if (hParentItem == m_tree.GetRootItem())
	{
		CString strParentText = m_tree.GetItemText(hParentItem);//如果根是一样的，直接拼接
		return strParentText + L"\\" + strItemText;

	}
	else
	{

		return GetTreePath(hParentItem) + L"\\" + strItemText;

	}


}


void C文件管理器Dlg::OnBnClickedButton4()
{
	UpdateData(true);

	int cnt = m_combox.GetCount();
	if (cnt > 5)
	{
		m_combox.DeleteString(cnt - 1);
	}


	m_combox.InsertString(0, m_strCurrent);


	Find(m_strCurrent, NULL);


	UpdateData(false);
}


void C文件管理器Dlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);


	//限制最小大小有两种方法：
#if 0
	//1.
	CRect screenRect;
	GetWindowRect(&screenRect);
	if (cx < 300)
	{
		cx = 300;
		MoveWindow(screenRect.left, screenRect.top,
			cx, cy);
	}
	if (cy < 300)
	{
		cy = 300;
		MoveWindow(screenRect.left, screenRect.top,
			cx, cy);
	}
	//限制大小存在异常，最小大小时，刷新出现问题
#else
	//2.
	/*
	使用消息：OnGetMinMaxInfo(MINMAXINFO* lpMMI)
	*/

#endif


	//获取客户区大小和位置：
	CRect rect;
	GetClientRect(&rect);


	//combox   只变宽度：
	if (m_combox.GetSafeHwnd())
	{
		//获取combox的大小：
		CRect comboRect;
		m_combox.GetWindowRect(&comboRect);

		ScreenToClient(&comboRect);	//屏幕转客户区
		//根据当前情况调整其大小：
		comboRect.right = rect.right - 270;
		m_combox.MoveWindow(&comboRect);

	}


	//按钮：
	if (GetDlgItem(IDC_BUTTON4))
	{
		CRect buttonRect;
		GetDlgItem(IDC_BUTTON4)->GetWindowRect(&buttonRect);

		int btnwidth = buttonRect.right - buttonRect.left;

		ScreenToClient(&buttonRect);

		buttonRect.right = rect.right - 163;
		buttonRect.left = buttonRect.right - btnwidth;


		GetDlgItem(IDC_BUTTON4)->MoveWindow(&buttonRect);
	}

	//树控件：
	if (m_tree.GetSafeHwnd())
	{
		CRect treeRect;
		m_tree.GetWindowRect(&treeRect);

		ScreenToClient(&treeRect);	//屏幕转客户区
		//根据当前情况调整其大小：
		treeRect.bottom = rect.bottom - 20;

		m_tree.MoveWindow(&treeRect);

	}

	//list控件：
	if (m_list.GetSafeHwnd())
	{
		CRect listRect;
		m_list.GetWindowRect(&listRect);

		ScreenToClient(&listRect);	//屏幕转客户区
		//根据当前情况调整其大小：
		listRect.bottom = rect.bottom - 20;
		listRect.right = rect.right - 20;

		m_list.MoveWindow(&listRect);

	}


}


void C文件管理器Dlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	//设置最小窗口大小：
	lpMMI->ptMinTrackSize.x = 314;
	lpMMI->ptMinTrackSize.y =480 ;

	CDialogEx::OnGetMinMaxInfo(lpMMI);
}
